
#include <string>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <unistd.h>
#include <random>
#include <chrono>
#include <sys/syscall.h> // SYS_gettid
#include <climits> // for HOST_NAME_MAX


class csvWriter {
    std::string csvName_;
    std::ofstream file;
    uint64_t interval_ = 0;
    uint64_t lastTimestamp_ = 0;
    decltype(getpid()) pid_ = getpid();
    decltype(getpid()) tid_ = syscall(SYS_gettid);

  public:
    template <typename... Args>
    csvWriter(const char *csvName, Args... args) {
        char hostname[HOST_NAME_MAX + 1] = {0}; // 分配足够大的缓冲区
        if (gethostname(hostname, sizeof(hostname))) {
            perror("gethostname failed");
        }
        auto outputPath = std::getenv("PROF_CSV_OUTPUT_PATH");

        csvName_ = outputPath + std::string(csvName) + "_" + hostname + "_" + std::to_string(getpid()) + ".csv";
        file.open(csvName_, std::ios::out);
        writeRow("pid", "tid", "time(ns)", args...);
    }

    ~csvWriter() { file.close(); }

    void setFlushInterval(uint64_t interval) {
        interval_ = interval;
    }

    template <typename... Args>
    void addRow(Args... args) {
        auto now = std::chrono::high_resolution_clock::now();
        auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
            now.time_since_epoch()
        ).count();
        writeRow(pid_, tid_, timestamp, args...);
        if (interval_ == 0 || interval_ < timestamp - lastTimestamp_) {
            file.flush();
            lastTimestamp_ = timestamp;
        }
    }
private:
    template <typename... Args>
    void writeRow(Args... args) {
        (void)std::initializer_list<int>{
            (file << args << ",", 0)...
        };
        file << "\n";
    }
};

#define DEFINE_CSV(csvName, ...) \
    thread_local static csvWriter csv##csvName(#csvName, __VA_ARGS__)
#define SET_FLUSH_INTERVAL(csvName, interval) csv##csvName.setFlushInterval(interval)
#define ADD_ROW(csvName, ...) csv##csvName.addRow(__VA_ARGS__)
